package com.xuecheng.media.jobhandler;

import com.xuecheng.base.utils.Mp4VideoUtil;
import com.xuecheng.media.model.po.MediaProcess;
import com.xuecheng.media.service.MediaFileProcessService;
import com.xuecheng.media.service.MediaFileService;
import com.xxl.job.core.context.XxlJobHelper;
import com.xxl.job.core.handler.annotation.XxlJob;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

@Component
@Slf4j
public class VideoTask {

    @Autowired
    MediaFileProcessService mediaFileProcessService;
    @Autowired
    MediaFileService mediaFileService;
    @Value("${videoprocess.ffmpegpath}")
    String ffmpegpath;

    @XxlJob("videoJobHandler")
    public void videoJobHandler() throws Exception {
        int shardIndex = XxlJobHelper.getShardIndex();
        int shardTotal = XxlJobHelper.getShardTotal();
        System.out.println("======执行任务调度======");
        //查询待处理的任务
        int cpu = Runtime.getRuntime().availableProcessors();
        List<MediaProcess> mediaProcessList = mediaFileProcessService.getMediaProcessList(shardIndex, shardTotal, cpu);
        //任务数量
        int size = mediaProcessList.size();

        //创建线程池
        ExecutorService threadPool = Executors.newFixedThreadPool(size);
        //计数器
        CountDownLatch countDownLatch = new CountDownLatch(size);
        //处理任务
        try {
            mediaProcessList.forEach(mediaProcess -> {
                threadPool.execute(() -> {
                    //任务id
                    Long taskId = mediaProcess.getId();
                    //抢占任务
                    boolean b = mediaFileProcessService.startTask(taskId);
                    if (!b){
                        log.debug("任务抢占失败，{}",mediaProcess);
                        return;
                    }
                    String bucket = mediaProcess.getBucket();
                    String filePath = mediaProcess.getFilePath();
                    String fileMd5 = mediaProcess.getFileId();
                    String filename = mediaProcess.getFilename();
                    //从minio下载待处理文件
                    File originalFile = mediaFileService.downloadFileFromMinIO(bucket, filePath);
                    if (originalFile==null){
                        log.debug("从minio下载待处理文件失败，{}",mediaProcess);
                        mediaFileProcessService.saveProcessFinishStatus(taskId,"3",fileMd5,null,"从minio下载待处理文件");
                        return;
                    }
                    //生成临时文件
                    File mp4File=null;
                    try {
                        mp4File=File.createTempFile("mp4",".mp4");
                    } catch (IOException e) {
                        log.debug("生成临时文件失败，{}",mediaProcess);
                        mediaFileProcessService.saveProcessFinishStatus(taskId,"3",fileMd5,null,"生成临时文件失败");
                        return;
                    }
                   // 转为MP4
                    //视频处理结果
                    String result = "";
                    try {
                        Mp4VideoUtil videoUtil = new Mp4VideoUtil(ffmpegpath, originalFile.getAbsolutePath(), mp4File.getName(), mp4File.getAbsolutePath());
                        result = videoUtil.generateMp4();
                    } catch (Exception e) {
                        log.debug("转码失败，{}",mediaProcess);
                        e.printStackTrace();
                    }
                    if (result!="success"){
                        log.debug("转码失败，{}",mediaProcess);
                        mediaFileProcessService.saveProcessFinishStatus(taskId,"3",fileMd5,null,"转码失败");
                        return;
                    }
                    String objectName = mediaFileService.getFilePathByMd5(fileMd5, ".mp4");
                    String url = "/" + bucket + "/" + objectName;
                    try {
                        //转码成功，上传到minio
                        mediaFileService.addMediaFilesToMinIO(mp4File.getAbsolutePath(),"video/mp4",bucket,objectName);
                    } catch (Exception e) {
                        log.debug("上传minio失败，{}",mediaProcess);
                        mediaFileProcessService.saveProcessFinishStatus(taskId,"3",fileMd5,null,"上传minio失败");
                        e.printStackTrace();
                    }
                    //更新视频处理表，并将成功的记录删除后上传到历史表
                    try {
                        mediaFileProcessService.saveProcessFinishStatus(taskId,"2",fileMd5,url,"");
                    } catch (Exception e) {
                        log.debug("更新数据库失败，{}",mediaProcess);
                        e.printStackTrace();
                    }

                });

            });
        } finally {
            countDownLatch.countDown();//--任务数
        }
        countDownLatch.await(30, TimeUnit.MINUTES);//阻塞
    }
}
